package cn.rgb.orm.parser;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import cn.rgb.orm.config.ResultMapping;
import cn.rgb.orm.config.SqlMapConfig;
import cn.rgb.orm.config.SqlMapping;
import cn.rgb.orm.config.SqlOperateMapping;

public class SqlMapConfigParser {
	
	private SAXBuilder builder = new SAXBuilder();
	private SqlMapConfig sqlMapConfig;

	public SqlMapConfig parse(String path) {
		if(sqlMapConfig == null)
			sqlMapConfig = new SqlMapConfig();
		List<String> paths = parseDataSource(path);
		for(String sqlMapPath : paths) {
			parseSqlMap(sqlMapPath);
		}
		return sqlMapConfig;
	}
	
	
	private List<String> parseDataSource(String path) {
		List<String> paths = new ArrayList<String>();
		try {
			Document doc = builder.build(path);
			Element rootEle = doc.getRootElement();
			List<Element>  dsPropEle = rootEle.getChild("transactionManager").getChild("dataSource").getChildren();
			for(Element ele : dsPropEle) {
				String name = ele.getAttributeValue("name");
				String value = ele.getAttributeValue("value");
				sqlMapConfig.putDsInfo(name, value);
			}
			List<Element> sqlMapEle = rootEle.getChildren("sqlMap");
			for(Element ele : sqlMapEle) {
				paths.add(ele.getAttributeValue("resource"));
			}
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return paths;
	}
	
	private void parseSqlMap(String path) {
		try {
			Document doc = builder.build(path);
			Element rootEle = doc.getRootElement();
			String namespace = rootEle.getAttributeValue("namespace");
			SqlMapping sqlMapping = sqlMapConfig.getSqlMapping(namespace);
			if(sqlMapping == null) {
				sqlMapping = new SqlMapping();
				sqlMapping.setNamespace(namespace);
				sqlMapConfig.addSqlMapping(sqlMapping);
			}
			parseAlias(rootEle, sqlMapping);
			parseResultMap(rootEle, sqlMapping);
			parseInsert(rootEle, sqlMapping);
			parseDelete(rootEle, sqlMapping);
			parseUpdate(rootEle, sqlMapping);
			parseSelect(rootEle, sqlMapping);
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void parseAlias(Element rootEle, SqlMapping sqlMapping) {
		List<Element> eles = rootEle.getChildren("typeAlias");
		for(Element ele : eles) {
			String alias = ele.getAttributeValue("alias");
			String type = ele.getAttributeValue("type");
			sqlMapping.putAlias(alias, type);
		}
	}
	
	private void parseResultMap(Element rootEle, SqlMapping sqlMapping) {
		ResultMapping resultMapping = new ResultMapping();
		List<Element> resultMapEles = rootEle.getChildren("resultMap");
		for(Element resultMapEle : resultMapEles) {
			String id = resultMapEle.getAttributeValue("id");
			resultMapping.setId(id);
			String clazz = resultMapEle.getAttributeValue("class");
			resultMapping.setClazz(clazz);
			List<Element> resultEles = resultMapEle.getChildren("result");
			for(Element resultEle : resultEles) {
				String property = resultEle.getAttributeValue("property");
				String column = resultEle.getAttributeValue("column");
				resultMapping.addPropColMap(property, column);
			}
			sqlMapping.addResultMapping(resultMapping);
		}
	}
	
	private void parseInsert(Element rootEle, SqlMapping sqlMapping) {
		parseSqlAction(rootEle, sqlMapping, "insert");
	}
	
	private void parseDelete(Element rootEle, SqlMapping sqlMapping) {
		parseSqlAction(rootEle, sqlMapping, "delete");
	}
	
	private void parseUpdate(Element rootEle, SqlMapping sqlMapping) {
		parseSqlAction(rootEle, sqlMapping, "update");
	}
	
	private void parseSelect(Element rootEle, SqlMapping sqlMapping) {
		parseSqlAction(rootEle, sqlMapping, "select");
	}
	
	
	
	private void parseSqlAction(Element rootEle, SqlMapping sqlMapping, String sqlAction) {
		List<Element> actionEles = rootEle.getChildren(sqlAction);
		for(Element actionEle : actionEles) {
			SqlOperateMapping sqlOperMapping = new SqlOperateMapping();
			String id = actionEle.getAttributeValue("id");
			sqlOperMapping.setId(id);
			String parameterClass = actionEle.getAttributeValue("parameterClass");
			sqlOperMapping.setParameterClass(parameterClass);
			String resultClass = actionEle.getAttributeValue("resultClass");
			sqlOperMapping.setResultClass(resultClass);
			String sql = actionEle.getTextTrim();
			sqlOperMapping.setSql(sql);
			sqlMapping.addSqlOperateMapping(sqlOperMapping);
		}
	}
}
